class Array:
    def __init__(self, size):
        self._size = size
        self._items = [None] * 20

    def __getitem__(self, index):
        return self._items[index]

    def __setitem__(self, index, value):
        self._items[index] = value

    def __len__(self):
        return self._size

    def clear(self, value=None):
        for i in range(len(self._items)):
            self._items[i] = value

    def __iter__(self):
        for item in self._items:
            yield item


class FullError(Exception):
    pass


class EmptyError(Exception):
    pass


class ArrayQueue:
    """
    相当于有两个指针，一个指向进，一个指向出，
    """

    def __init__(self, maxsize):
        self.maxsize = maxsize
        self.array = Array(maxsize)
        self.head = 0
        self.tail = 0

    def __len__(self):
        return self.head - self.tail

    def push(self, value):
        if len(self) >= self.maxsize:
            raise FullError('full')
        self.array[self.head % self.maxsize] = value  # 第一次是head = 0
        self.head += 1

    def pop(self):
        if len(self) <= 0:
            raise EmptyError('empty')
        value = self.array[self.tail % self.maxsize]
        self.tail += 1
        return value


def test_arrayqueue():
    maxsize = 5
    q = ArrayQueue(maxsize)
    for i in range(maxsize):
        q.push(i)

    assert len(q) == 5
    import pytest
    with pytest.raises(FullError) as e:
        q.push(maxsize)
    assert 'full' in str(e.value)

    assert q.pop() == 0
    assert q.pop() == 1
    assert q.pop() == 2
    assert q.pop() == 3
    assert q.pop() == 4
    with pytest.raises(EmptyError) as e1:
        q.pop()
    assert 'empty' in str(e1.value)
